package faktorI;

public class Parser {
	Pravilo pravilo;
	Zakljucak zakljucak;
	Preduslov preduslov;
	double faktorI;
	private Tokenstream ts;
	public Parser(Tokenstream ts){ 
		this.ts = ts;
		preduslov = new Preduslov();
	}
	
	public void parsirajPrav(){
		if(ts.tok == Scaner.AKO){
			ts.next();
			preduslov();
			if(ts.tok == Scaner.ONDA){
				ts.next();
				if(ts.tok == '('){
					ts.next();
					faktorI();
					if(ts.tok == ')'){
						ts.next();
						zakljucak();
					}
					else throw ts.greskaParsera("Očekivana ')'");
				}
				else throw ts.greskaParsera("Očekivana '('");
			}
			else throw ts.greskaParsera("Očekivano 'ONDA'");
		}
		else throw ts.greskaParsera("Očekivano 'AKO'");
	}
	public void preduslov(){
		i_list();
		ili_opt();
		return;
	}
	public void faktorI(){
		if(ts.tok == Scaner.DOUBLE){
			faktorI = obradaFaktoraI(ts.nval);
			ts.next();
		}
		else throw ts.greskaParsera("Očekivan broj ");
	}
	
	public void i_list(){
		deo_pred();i_opt();
	}
	public void ili_opt(){
		if(ts.tok == Scaner.ILI){ 
			preduslov.dodajPredElem(new PredElem(ts));
			ts.next();i_list();ili_opt();
		}
		return;
	}
	public void i_opt(){
		if(ts.tok == Scaner.I){
			preduslov.dodajPredElem(new PredElem(ts));
			ts.next();deo_pred();i_opt();
		}
		return;
	}
	public void  deo_pred(){
		switch (ts.tok) {
		case Scaner.WORD:
			preduslov.dodajPredElem(new PredElem(ts));
			ts.next(); return;
		case '-':
			ts.next();
			if(ts.tok == Scaner.WORD){
				preduslov.dodajPredElem(new PredElem(ts, true));
				ts.next();
				return;
			}
			else throw ts.greskaParsera("Očekivan preduslov ");
		case '(':
			preduslov.dodajPredElem(new PredElem(ts));
			ts.next();
			preduslov();
			if (ts.tok != ')')throw ts.greskaParsera("Očekivana ')'");
			preduslov.dodajPredElem(new PredElem(ts));
			ts.next();
			return;
		default:
			throw ts.greskaParsera("Očekivan preduslov ili '('");
		}
	}
	
	public void zakljucak(){
		if(ts.tok == Scaner.WORD){
			zakljucak = new Zakljucak(ts);
			ts.next();
			return;
		}
		else
			throw ts.greskaParsera("Očekivan zakljucak ");
	
	}
	
	public Pravilo parse(Pravilo pravilo) throws Greska{
		parsirajPrav();
		pravilo.setPreudslov(preduslov);
		pravilo.setZakljucak(zakljucak);
		pravilo.setFaktorI(faktorI);
		return pravilo;
	}
	
	
	private double obradaFaktoraI(Double vrednost){
		  if(vrednost > 1 || vrednost <-1)
			  throw new Greska("Faktor izvesnosti mora biti između -1 i 1 ");
		  else return vrednost;
	} 
}
